home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 August: Tool Chest / Dev.CD Aug 98 TC.toast / Sample Code / Networking / GetSetOptions1.0d1 / GetSetOptions.c < prev    next >
Encoding:
Text File  |  1997-07-14  |  14.3 KB  |  503 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        GetSetOptions.c
  3.  
  4.     Contains:    Sample for getting and setting options using the various
  5.                 option management routines.
  6.  
  7.     Written by:    Quinn "The Eskimo!"
  8.  
  9.     Copyright:    © 1997 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.  
  13.     You may incorporate this sample code into your applications without
  14.     restriction, though the sample code has been provided "AS IS" and the
  15.     responsibility for its operation is 100% yours.  However, what you are
  16.     not permitted to do is to redistribute the source as "DSC Sample Code"
  17.     after having made changes. If you're going to re-distribute the source,
  18.     we require that you make it clear in the source that the code was
  19.     descended from Apple Sample Code, but that you've made changes.
  20. */
  21.  
  22. /////////////////////////////////////////////////////////////////////
  23. // The OT debugging macros in <OTDebug.h> require this variable to
  24. // be set.
  25.  
  26. #ifndef qDebug
  27. #define qDebug    1
  28. #endif
  29.  
  30. /////////////////////////////////////////////////////////////////////
  31. // Pick up all the standard OT stuff.
  32.  
  33. #include <OpenTransport.h>
  34.  
  35. /////////////////////////////////////////////////////////////////////
  36. // Pick up all the OT TCP/IP stuff.
  37.  
  38. #include <OpenTptInternet.h>
  39.  
  40. /////////////////////////////////////////////////////////////////////
  41. // Pick up all the OT serial stuff.
  42.  
  43. #include <OpenTptSerial.h>
  44.  
  45. /////////////////////////////////////////////////////////////////////
  46. // Pick up the OTDebugBreak and OTAssert macros.
  47.  
  48. #include <OTDebug.h>
  49.  
  50. /////////////////////////////////////////////////////////////////////
  51. // Standard C prototypes.
  52.  
  53. #include <stdio.h>
  54.  
  55. /////////////////////////////////////////////////////////////////////
  56. // OTDebugStr is not defined in any OT header files, but it is
  57. // exported by the libraries, so we define the prototype here.
  58.  
  59. extern pascal void OTDebugStr(const char* str);
  60.  
  61. /////////////////////////////////////////////////////////////////////
  62.  
  63. static OTResult SetFourByteOption(EndpointRef ep,
  64.                                     OTXTILevel level,
  65.                                     OTXTIName  name,
  66.                                     UInt32       value)
  67.     // level and name must denote a four byte option that is
  68.     // appropriate for the endpoint ep.  This routine sets the
  69.     // option to value.  ep is assumed to be in synchronous
  70.     // mode.
  71.     //
  72.     // If all goes well, the result is noErr.  If an error
  73.     // occurs, the result is negative.  If the option could not
  74.     // be negotiated, a positive result being one of (T_FAILURE,
  75.     // T_PARTSUCCESS, T_READONLY, T_NOTSUPPORT) is returned
  76. {
  77.     OTResult    err;
  78.     TOption        option;
  79.     TOptMgmt    request;
  80.     TOptMgmt    result;
  81.     
  82.     // Set up the option buffer to reflect the specific option
  83.     // and value we want to set.  We use a TOption structure
  84.     // to represent the option buffer.  TOption is specifically
  85.     // defined to allow easy construction of 4 byte options.
  86.     // If you want to negotiate different size options, or
  87.     // multiple options in a single call, then constructing
  88.     // the option buffer is a little trickier
  89.     
  90.     option.len        = kOTFourByteOptionSize;
  91.     option.level    = level;
  92.     option.name        = name;
  93.     option.status     = 0;
  94.     option.value[0] = value;
  95.  
  96.     // Set up the request for OTOptionManagement to point
  97.     // to the option buffer we just filled out, and tell
  98.     // it that we want to negotiate (ie set) the option.
  99.     
  100.     request.opt.buf    = (UInt8 *) &option;
  101.     request.opt.len    = sizeof(option);
  102.     request.flags    = T_NEGOTIATE;
  103.  
  104.     // Set up the reply for OTOptionManagement.  This is where
  105.     // OTOptionManagement puts the result of the negotiation.
  106.     
  107.     result.opt.buf = (UInt8 *) &option;
  108.     result.opt.maxlen = sizeof(option);
  109.  
  110.     // Call OTOptionManagement and then check that the value
  111.     // was negotiated successfully.  Any value other than
  112.     // T_SUCCESS is reported via the error result.
  113.     
  114.     err = OTOptionManagement(ep, &request, &result);
  115.  
  116.     if (err == noErr) {
  117.         if (option.status != T_SUCCESS) {
  118.             err = option.status;
  119.         }
  120.     }
  121.                 
  122.     return (err);
  123. }
  124.  
  125. /////////////////////////////////////////////////////////////////////
  126.  
  127. static OTResult GetFourByteOption(EndpointRef ep,
  128.                                     OTXTILevel level,
  129.                                     OTXTIName  name,
  130.                                     UInt32       *value)
  131.     // level and name must denote a four byte option that is
  132.     // appropriate for the endpoint ep.  This routine gets the
  133.     // current option setting and puts it in the the variable
  134.     // pointed to by value.  ep is assumed to be in synchronous
  135.     // mode.
  136.     //
  137.     // If all goes well, the result is noErr.  If an error
  138.     // occurs, the result is negative.  If the option could not
  139.     // be read, a positive result being one of (T_FAILURE,
  140.     // T_PARTSUCCESS, T_NOTSUPPORT) is returned
  141. {
  142.     OTResult    err;
  143.     TOption        option;
  144.     TOptMgmt    request;
  145.     TOptMgmt    result;
  146.     
  147.     // Set up the option buffer to reflect the specific option
  148.     // and value we want to set.  We use a TOption structure
  149.     // to represent the option buffer.  TOption is specifically
  150.     // defined to allow easy construction of 4 byte options.
  151.     // If you want to negotiate different size options, or
  152.     // multiple options in a single call, then constructing
  153.     // the option buffer is a little trickier
  154.     
  155.     option.len        = kOTFourByteOptionSize;
  156.     option.level    = level;
  157.     option.name        = name;
  158.     option.status     = 0;
  159.     option.value[0] = 0;    // Ignored because we're getting the value.
  160.  
  161.     // Set up the request for OTOptionManagement to point
  162.     // to the option buffer we just filled out, and tell
  163.     // it that we want to get the current value of the option.
  164.     
  165.     request.opt.buf    = (UInt8 *) &option;
  166.     request.opt.len    = sizeof(option);
  167.     request.flags    = T_CURRENT;
  168.  
  169.     // Set up the reply for OTOptionManagement.  This is where
  170.     // OTOptionManagement puts the result of the negotiation.
  171.     
  172.     result.opt.buf = (UInt8 *) &option;
  173.     result.opt.maxlen = sizeof(option);
  174.  
  175.     // Call OTOptionManagement and then check that the value
  176.     // was read successfully.  Any status other than
  177.     // T_SUCCESS or T_READONLY is reported via the error
  178.     // result.
  179.     
  180.     err = OTOptionManagement(ep, &request, &result);
  181.  
  182.     if (err == noErr) {
  183.         switch (option.status) {
  184.             case T_SUCCESS:
  185.             case T_READONLY:
  186.                 *value = option.value[0];
  187.                 break;
  188.             default:
  189.                 err = option.status;
  190.                 break;
  191.         }
  192.     }
  193.                 
  194.     return (err);
  195. }
  196.  
  197. /////////////////////////////////////////////////////////////////////
  198.  
  199. static OSStatus PrintOptionBuffer(const TNetbuf *optionBuffer)
  200.     // Print a summary of the optionBuffer to stdout.
  201.     // Basically the call enumerates the option buffer using
  202.     // OTNextOption, and prints the level, name, size and status
  203.     // of each of the options in the buffer.
  204. {
  205.     OSStatus err;
  206.     TOption    *currentOption;
  207.  
  208.     currentOption = nil;
  209.     do {
  210.         err = OTNextOption(optionBuffer->buf, optionBuffer->len, ¤tOption);
  211.         if (err == noErr && currentOption != nil) {
  212.             printf("Level = $%08x, Name = $%08x, Data Length = %d, Status = $%08x\n",
  213.                                 currentOption->level, 
  214.                                 currentOption->name, 
  215.                                 currentOption->len - kOTOptionHeaderSize,
  216.                                 currentOption->status);
  217.         }
  218.     } while (err == noErr && currentOption != nil);
  219.     
  220.     return (err);
  221. }
  222.  
  223. /////////////////////////////////////////////////////////////////////
  224.  
  225. static OSStatus PrintAllOptionsAtLevel(EndpointRef ep, OTXTILevel level)
  226.     // Gets all of the options for the endpoint ep at the specified
  227.     // level and prints a summary of them to stdout.
  228. {
  229.     OSStatus        err;
  230.     TEndpointInfo    epInfo;
  231.     TOptionHeader    requestOption;
  232.     void            *resultOptionBuffer;
  233.     TOptMgmt        request;
  234.     TOptMgmt        result;
  235.  
  236.     resultOptionBuffer = nil;
  237.  
  238.     // First call OTGetEndpointInfo to find out the maximum
  239.     // size of the options for this type of endpoint and then
  240.     // allocate that size buffer to hold the resulting options.
  241.     
  242.     err = OTGetEndpointInfo(ep, &epInfo);
  243.     if (err == noErr) {
  244.         resultOptionBuffer = OTAllocMem(epInfo.options);
  245.         if (resultOptionBuffer == nil) {
  246.             err = kENOMEMErr;
  247.         }
  248.     }
  249.     
  250.     // Call OTOptionManagement to get the current value (T_CURRENT)
  251.     // of all of the options (ie T_ALLOPT) of the specified level.
  252.     // The resulting options go into resultOptionBuffer, which we
  253.     // have just allocated.
  254.  
  255.     if (err == noErr) {
  256.         requestOption.len        = kOTOptionHeaderSize;
  257.         requestOption.level        = level;
  258.         requestOption.name        = T_ALLOPT;
  259.         requestOption.status     = 0;
  260.  
  261.         request.opt.buf    = (UInt8 *) &requestOption;
  262.         request.opt.len    = sizeof(requestOption);
  263.         request.flags    = T_CURRENT;
  264.         
  265.         result.opt.buf = resultOptionBuffer;
  266.         result.opt.maxlen = epInfo.options;
  267.         
  268.         err = OTOptionManagement(ep, &request, &result);
  269.     }
  270.     
  271.     // Now that we have the options, print them to stdout.
  272.     
  273.     if (err == noErr) {
  274.         err = PrintOptionBuffer(&result.opt);
  275.         printf("\n");
  276.     }
  277.     
  278.     // Clean up.
  279.     
  280.     if (resultOptionBuffer != nil) {
  281.         OTFreeMem(resultOptionBuffer);
  282.     }
  283.     
  284.     return (err);
  285. }
  286.  
  287. /////////////////////////////////////////////////////////////////////
  288.  
  289. static OSStatus PrintOptionsForConfiguration(const char *configStr, OTXTILevel level)
  290.     // Get all the options associated with a specific level of a specific
  291.     // OT provider (eg configStr) and then convert those options to a
  292.     // formatted string and output that string.
  293. {
  294.     OSStatus        err;
  295.     OSStatus        junk;
  296.     EndpointRef        ep;
  297.     TEndpointInfo    epInfo;
  298.     TOptionHeader    requestOption;
  299.     void            *resultOptionBuffer;
  300.     TOptMgmt        request;
  301.     TOptMgmt        result;
  302.     TOption            *resultOption;
  303.     char            optionsString[1024];
  304.  
  305.     resultOptionBuffer = nil;
  306.     ep = kOTInvalidEndpointRef;
  307.     
  308.     // First create an endpoint using the specified configuration.
  309.     // Note that we pass in epInfo to be filled out with the various
  310.     // parameters of this endpoint, including it's maximum option
  311.     // buffer size.
  312.     
  313.     ep = OTOpenEndpoint(OTCreateConfiguration(configStr), 0, &epInfo, &err);
  314.  
  315.     // Now allocate a buffer of the maximum option buffer size.
  316.     
  317.     if (err == noErr) {
  318.         resultOptionBuffer = OTAllocMem(epInfo.options);
  319.         if (resultOptionBuffer == nil) {
  320.             err = kENOMEMErr;
  321.         }
  322.     }
  323.  
  324.     // Call OTOptionManagement to get the current value (T_CURRENT)
  325.     // of all of the options (ie T_ALLOPT) of the specified level.
  326.     // The resulting options go into resultOptionBuffer, which we
  327.     // have just allocated.
  328.  
  329.     if (err == noErr) {
  330.         requestOption.len        = kOTOptionHeaderSize;
  331.         requestOption.level        = level;
  332.         requestOption.name        = T_ALLOPT;
  333.         requestOption.status     = 0;
  334.  
  335.         request.opt.buf    = (UInt8 *) &requestOption;
  336.         request.opt.len    = sizeof(requestOption);
  337.         request.flags    = T_CURRENT;
  338.         
  339.         result.opt.buf = resultOptionBuffer;
  340.         result.opt.maxlen = epInfo.options;
  341.         
  342.         err = OTOptionManagement(ep, &request, &result);
  343.     }
  344.     
  345.     // Now use OTCreateOptionString to convert the resulting
  346.     // buffer full of options into a formatted string, and then print
  347.     // that formatted string to stdout.
  348.     
  349.     if (err == noErr) {
  350.         resultOption = (TOption *) result.opt.buf;
  351.         err = OTCreateOptionString(configStr, &resultOption, result.opt.buf + result.opt.len, optionsString, 1024);
  352.         if (err == noErr) {
  353.             printf("Formatted Options = “%s”\n\n", optionsString);
  354.         }
  355.     }
  356.     
  357.     // Clean up.
  358.     
  359.     if (resultOptionBuffer != nil) {
  360.         OTFreeMem(resultOptionBuffer);
  361.     }
  362.     if (ep != kOTInvalidEndpointRef) {
  363.         junk = OTCloseProvider(ep);
  364.         OTAssert("PrintOptionsForConfiguration: Closing the endpoint failed", junk == noErr);
  365.     }
  366.     
  367.     return (err);
  368. }
  369.  
  370. /////////////////////////////////////////////////////////////////////
  371.  
  372. static OSStatus BuildAndPrintOptions(const char *configStr, const char *optionsString)
  373.     // Given a configuration string and a set of formatted options, converts
  374.     // the options to their binary format (ie an options buffer) and then
  375.     // prints that buffer to stdout.
  376. {
  377.     OSStatus err;
  378.     OSStatus junk;
  379.     void *resultOptionBuffer;
  380.     EndpointRef ep;
  381.     TEndpointInfo epInfo;
  382.     TNetbuf optionsNetbuf;
  383.     
  384.     resultOptionBuffer = nil;
  385.     ep = kOTInvalidEndpointRef;
  386.     
  387.     // First create an endpoint using the specified configuration.
  388.     // Note that we pass in epInfo to be filled out with the various
  389.     // parameters of this endpoint, including it's maximum option
  390.     // buffer size.
  391.  
  392.     ep = OTOpenEndpoint(OTCreateConfiguration(configStr), 0, &epInfo, &err);
  393.     
  394.     // Now allocate a buffer of the maximum option buffer size.
  395.  
  396.     if (err == noErr) {
  397.         resultOptionBuffer = OTAllocMem(epInfo.options);
  398.         if (resultOptionBuffer == nil) {
  399.             err = kENOMEMErr;
  400.         }
  401.     }
  402.  
  403.     // Call OTCreateOptions to parse the formatted optionsString into
  404.     // the binary format (optionsNetbuf), and then use PrintOptionBuffer
  405.     // to output that buffer to stdout.
  406.  
  407.     if (err == noErr) {
  408.         optionsNetbuf.buf = resultOptionBuffer;
  409.         optionsNetbuf.len = 0;
  410.         optionsNetbuf.maxlen = epInfo.options;
  411.         err = OTCreateOptions(configStr, (char **) &optionsString, &optionsNetbuf);
  412.         
  413.         if (err == noErr) {
  414.             err = PrintOptionBuffer(&optionsNetbuf);
  415.             printf("\n");
  416.         }
  417.     }
  418.     
  419.     // Clean up.
  420.     
  421.     if (resultOptionBuffer != nil) {
  422.         OTFreeMem(resultOptionBuffer);
  423.     }
  424.     if (ep != kOTInvalidEndpointRef) {
  425.         junk = OTCloseProvider(ep);
  426.         OTAssert("BuildAndPrintOptions: Closing the endpoint failed", junk == noErr);
  427.     }
  428.     
  429.     return (err);
  430. }
  431.  
  432. /////////////////////////////////////////////////////////////////////
  433.  
  434. void main(void)
  435.     // A simple main line that demonstrates the use of the various
  436.     // functions defined above.  The basic idea is to create
  437.     // an endpoint, get the value of the IP_REUSEADDR option, then
  438.     // change it to true, and read it back to verify that the change
  439.     // worked.  We then do a few other interesting things with
  440.     // various miscellaneous options API routines.
  441. {
  442.     OSStatus err;
  443.     OSStatus junk;
  444.     EndpointRef ep;
  445.     UInt32 value;
  446.     
  447.     printf("Hello Cruel World!\n");
  448.     
  449.     err = InitOpenTransport();
  450.     
  451.     if (err == noErr) {
  452.     
  453.         ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err);
  454.         if (err == noErr) {
  455.             
  456.             printf("\nGetting and Setting IP_REUSEADDR.\n");
  457.             
  458.             err = GetFourByteOption(ep, INET_IP, IP_REUSEADDR, &value);
  459.             if (err == noErr) {
  460.                 printf("Default value = %d\n", value);
  461.             }
  462.             if (err == noErr) {
  463.                 err = SetFourByteOption(ep, INET_IP, IP_REUSEADDR, true);
  464.             }
  465.             if (err == noErr) {
  466.                 err = GetFourByteOption(ep, INET_IP, IP_REUSEADDR, &value);
  467.                 if (err == noErr) {
  468.                     printf("New value = %d\n", value);
  469.                 }
  470.             }
  471.  
  472.             if (err == noErr) {
  473.                 printf("\nPrinting Options Piecemeal at Level INET_IP.\n");
  474.                 err = PrintAllOptionsAtLevel(ep, INET_IP);
  475.             }
  476.             
  477.             if (err == noErr) {
  478.                 printf("\nPrinting Formatted Options at Level COM_SERIAL.\n");
  479.                 err = PrintOptionsForConfiguration(kSerialName, COM_SERIAL);
  480.             }
  481.             
  482.             if (err == noErr) {
  483.                 printf("\nBuilding Options for COM_SERIAL.\n");
  484.                 err = BuildAndPrintOptions(kSerialName, "BaudRate=9600, DataBits=7, StopBits=15");
  485.             }
  486.             
  487.             junk = OTCloseProvider(ep);
  488.             OTAssert("GetSetOptions: Closing the endpoint failed", junk == noErr);
  489.         }
  490.         
  491.         CloseOpenTransport();
  492.     }
  493.     
  494.     if (err == noErr) {
  495.         printf("Success.\n");
  496.     } else {
  497.         printf("Failed with error %d.\n", err);
  498.     }
  499.     printf("Done.  Press command-Q to Quit.\n");
  500. }
  501.  
  502.  
  503.